home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libgutil / propdit.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  327 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    propdit -
  19.  *        general propagation dither support.
  20.  *
  21.  *            Paul Haeberli - 1993
  22.  */
  23. #include "stdio.h"
  24. #include "propdit.h"
  25.  
  26. #define NOISEMAG2    64
  27. #define NOISEPATS    1000
  28.  
  29. /*
  30.  *    noise adding stuff follows . . . 
  31.  *
  32.  */
  33. static initnoise(pd)
  34. propdit *pd;
  35. {
  36.     int n;
  37.     int *nptr;
  38.  
  39.     n = NOISEPATS+pd->xsize;
  40.     pd->noise = (int *)malloc(n*sizeof(int));
  41.     nptr = pd->noise;
  42.     srandom(getpid());
  43.     while(n--)
  44.     *nptr++ = 128+(random()%(NOISEMAG2+1))-(NOISEMAG2/2);
  45. }
  46.  
  47. /*
  48.  *    Cheap 2 weight dither
  49.  *
  50.  */
  51. static int bmditherrow2(pd,buf,bits)
  52. propdit *pd;
  53. short *buf;
  54. unsigned char *bits;
  55. {
  56.     int i, maskbit;
  57.     int error, rerror, rwant;
  58.     int *nptr;
  59.     int *error0, *error1;
  60.     int n;
  61.  
  62.     n = pd->xsize;
  63.     if(!pd->noise)
  64.     initnoise(pd);
  65.     nptr = pd->noise+(random()%NOISEPATS);
  66.     if(pd->cury&1) {
  67.     error0 = pd->err0+1;
  68.     error1 = pd->err1+1;
  69.     maskbit = 0x80;
  70.     for(i=0; i<n; i++ ) {
  71.         rerror = (error1[i-1]+error0[i])>>1;
  72.         if(*buf == 0 || *buf == 255) {
  73.         rwant = *buf + rerror;
  74.         if(*buf++ == 255) {
  75.             error =  rwant-255;
  76.         } else {
  77.             error =  rwant-0;
  78.             *bits |= maskbit;        
  79.         }
  80.         } else {
  81.         rwant = *buf++ + rerror;
  82.         if(rwant>*nptr++) {
  83.             error =  rwant-255;
  84.         } else {
  85.             error =  rwant-0;
  86.             *bits |= maskbit;        
  87.         }
  88.         }
  89.         error1[i] = error;
  90.         maskbit >>= 1;
  91.         if(!maskbit) {
  92.         maskbit = 0x80;
  93.         bits++;
  94.         }
  95.     }
  96.     } else {
  97.     error0 = pd->err1+1;
  98.     error1 = pd->err0+1;
  99.     buf+=(n-1);
  100.     bits = bits + ((n-1)/8);
  101.     maskbit = 0x80>>((n-1)%8);
  102.     for(i=n; i--;) {
  103.         rerror = (error1[i+1]+error0[i])>>1;
  104.         if(*buf == 0 || *buf == 255) {
  105.         rwant = *buf + rerror;
  106.         if(*buf-- == 255) {
  107.             error =  rwant-255;
  108.         } else {
  109.             error =  rwant-0;
  110.             *bits |= maskbit;        
  111.         }
  112.         } else {
  113.         rwant = *buf-- + rerror;
  114.         if(rwant>*nptr++) {
  115.             error =  rwant-255;
  116.         } else {
  117.             error =  rwant-0;
  118.             *bits |= maskbit;        
  119.         }
  120.         }
  121.         error1[i] = error;
  122.         maskbit <<= 1;
  123.         if(maskbit&0x100) {
  124.         maskbit = 0x01;
  125.         bits--;
  126.         }
  127.     }
  128.     }
  129. }
  130.  
  131. #define ERRMAG3    64
  132.  
  133. /*
  134.  *    Use 3 spots to contribute error . . .
  135.  *
  136.  */
  137. static int bmditherrow3(pd,buf,bits)
  138. propdit *pd;
  139. short *buf;
  140. unsigned char *bits;
  141. {
  142.     int n, i, maskbit;
  143.     int error, rerror, rnext, rwant;
  144.     int *error0;
  145.  
  146.     n = pd->xsize;
  147.     maskbit = 0x80;
  148.     rerror = (random()%ERRMAG3)-(ERRMAG3/2);
  149.     error0 = pd->err0+1;
  150.     rnext = error0[0] = 0;
  151.     for(i=0; i<n; i++ ) {
  152.     rwant = *buf++ + rerror + rnext;
  153.     if(rwant>128) {
  154.         error =  rwant-255;
  155.     } else {
  156.         error =  rwant-0;
  157.         *bits |= maskbit;        
  158.     }
  159.     rerror = (3*error)/8;
  160.     error0[i] += rerror;
  161.     rnext = error0[i+1];
  162.     error0[i+1] = error-2*rerror;
  163.     maskbit = maskbit>>1;
  164.     if(!maskbit) {
  165.         maskbit = 0x80;
  166.         bits++;
  167.     }
  168.     }
  169. }
  170.  
  171. /*
  172.  *    Thad suggested this technique. Uses 4 spots to contribute error.
  173.  *
  174.  */
  175. static int bmditherrow4(pd,buf,bits)
  176. propdit *pd;
  177. short *buf;
  178. unsigned char *bits;
  179. {
  180.     int n, i, maskbit;
  181.     int error, rerror, rwant;
  182.     int *error0, *error1;
  183.  
  184.     n = pd->xsize;
  185.     if(pd->cury&1) {
  186.     error0 = pd->err0+1;
  187.     error1 = pd->err1+1;
  188.     } else {
  189.     error0 = pd->err1+1;
  190.     error1 = pd->err0+1;
  191.     }
  192.     maskbit = 0x80;
  193.     for(i=0; i<n; i++ ) {
  194.     rerror = (error1[i-1]+error0[i-1]+error0[i]+error0[i+1]+2)>>2;
  195.     rwant = *buf++ + rerror;
  196.     if(rwant>128) {
  197.         error =  rwant-255;
  198.     } else {
  199.         error =  rwant-0;
  200.         *bits |= maskbit;        
  201.     }
  202.     error1[i] = error;
  203.     maskbit = maskbit>>1;
  204.     if(!maskbit) {
  205.         maskbit = 0x80;
  206.         bits++;
  207.     }
  208.     }
  209. }
  210.  
  211. /*
  212.  *    True Floyd and Steinberg dither
  213.  *
  214.  */
  215. static int bmditherrowfloyd(pd,buf,bits)
  216. propdit *pd;
  217. short *buf;
  218. unsigned char *bits;
  219. {
  220.     int n, i, maskbit;
  221.     int error, rerror, rwant;
  222.     int *error0, *error1;
  223.  
  224.     n = pd->xsize;
  225.     maskbit = 0x80;
  226.     if(pd->cury&1) {
  227.     error0 = pd->err0+1;
  228.     error1 = pd->err1+1;
  229.     for(i=0; i<n; i++ ) {
  230.         rerror = (7*error1[i-1]+error0[i-1]+5*error0[i]+3*error0[i+1]+2)>>4;
  231.         rwant = *buf++ + rerror;
  232.         if(rwant>128) {
  233.         error =  rwant-255;
  234.         } else {
  235.         error =  rwant-0;
  236.         *bits |= maskbit;        
  237.         }
  238.         error1[i] = error;
  239.         maskbit >>= 1;
  240.         if(!maskbit) {
  241.         maskbit = 0x80;
  242.         bits++;
  243.         }
  244.     }
  245.     } else {
  246.     error0 = pd->err1+1;
  247.     error1 = pd->err0+1;
  248.     buf+=(n-1);
  249.     maskbit = 0x80>>((n-1)%8);
  250.     bits = bits + ((n-1)/8);
  251.     for(i=n; i--;) {
  252.         rerror = (7*error1[i+1]+error0[i+1]+5*error0[i]+3*error0[i-1]+2)>>4;
  253.         rwant = *buf-- + rerror;
  254.         if(rwant>128) {
  255.         error =  rwant-255;
  256.         } else {
  257.         error =  rwant-0;
  258.         *bits |= maskbit;        
  259.         }
  260.         error1[i] = error;
  261.         maskbit <<= 1;
  262.         if(maskbit&0x100) {
  263.         maskbit = 0x01;
  264.         bits--;
  265.         }
  266.     }
  267.     }
  268. }
  269.  
  270. propdit *newpropdit(xsize,dittype)
  271. int xsize, dittype;
  272. {
  273.     propdit *pd;
  274.  
  275.     pd = (propdit *)malloc(sizeof(propdit));
  276.     switch(dittype) {
  277.      case PROPDIT2:
  278.         pd->ditfunc = bmditherrow2;
  279.         break;
  280.      case PROPDIT3:
  281.         pd->ditfunc = bmditherrow3;
  282.         break;
  283.      case PROPDIT4:
  284.         pd->ditfunc = bmditherrow4;
  285.         break;
  286.      case PROPDITFS:
  287.         pd->ditfunc = bmditherrowfloyd;
  288.         break;
  289.     default:
  290.         fprintf(stderr,"newpropdit: bad dittype %d\n",dittype);
  291.         exit(1);
  292.     }
  293.     pd->xsize = xsize;
  294.     pd->cury = 0;
  295.     pd->err0 = (int *)malloc((xsize+2)*sizeof(int));
  296.     pd->err1 = (int *)malloc((xsize+2)*sizeof(int));
  297.     bzero(pd->err0,(xsize+2)*sizeof(int));
  298.     bzero(pd->err1,(xsize+2)*sizeof(int));
  299.     pd->noise = 0;
  300.     return pd;
  301. }
  302.  
  303. freepropdit(pd)
  304. propdit *pd;
  305. {
  306.     if(pd->err0)
  307.     free(pd->err0);
  308.     if(pd->err1)
  309.     free(pd->err1);
  310.     if(pd->noise)
  311.     free(pd->noise);
  312.     free(pd);
  313. }
  314.  
  315. propditrow(pd,sbuf,bbuf)
  316. propdit *pd;
  317. short *sbuf;
  318. unsigned char *bbuf;
  319. {
  320.     int outbytes;
  321.  
  322.     outbytes = 1+((pd->xsize-1)>>3);
  323.     bzero(bbuf,outbytes);
  324.     pd->ditfunc(pd,sbuf,bbuf);
  325.     pd->cury++;
  326. }
  327.